﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Epic.Net.Utility;
using System.Net;
using Epic.Net.Extensions;


namespace Epic.Net
{
    public class BufferReader
    {

        public static BufferReader Default(byte[] buffer)
        {
            return new BufferReader(buffer, Encoding.Default);
        }


        public BufferReader(byte[] buffer) : this(buffer, Encoding.UTF8)
        {

        }

        public BufferReader(byte[] buffer, Encoding encoding)
        {
            this.Buffer = buffer;
            this.Encoding = encoding;
        }

        public Encoding Encoding
        {
            get;
            set;
        }

        public byte[] Buffer
        {
            get;
            set;
        }

        public int Position
        {
            get;
            set;
        }

        public int Length
        {
            get { return this.Buffer.Length; }
        }

        public int Seek(int offset)
        {
            if (offset != 0) 
                this.Position += offset;
            return this.Position;
        }

        public byte ReadByte(int offset = 0)
        {
            this.Seek(offset);
            return this.Buffer[this.Position++];
        }

        public bool ReadBool(int offset = 0)
        {
            return Convert.ToBoolean(this.ReadByte(offset));
        }

        public short ReadInt16(int offset = 0)
        {
            this.Seek(offset);
            return BitConverter.ToInt16(this.Buffer, this.Position).Action(() => this.Seek(sizeof(short)));
        }

        public int ReadInt32(int offset = 0)
        {
            this.Seek(offset);
            return BitConverter.ToInt32(this.Buffer, this.Position).Action(() => this.Seek(sizeof(int)));
        }

        public double ReadDouble(int offset = 0)
        {
            this.Seek(offset);
            return BitConverter.ToDouble(this.Buffer, this.Position).Action(() => this.Seek(sizeof(double)));
        }

        public string ReadString(int length = -1)
        {
            return this.ReadString(0, length);
        }

        public string ReadString(int offset, int length = -1)
        {
            this.Seek(offset);
            if (length == 0) return String.Empty;
            if (length == -1) length = this.Length - this.Position;
            return this.Encoding.GetString(this.Buffer, this.Position, length).Action(() => this.Seek(length));
        }

        public byte[] ReadBytes(int offset, int length)
        {
            var result = new byte[length];
            this.ReadBytes(offset, length, result, 0);
            return result;
        }

        public void ReadBytes(int offset, int length, byte[] target, int targetOffset)
        {
            this.Seek(offset);
            System.Buffer.BlockCopy(this.Buffer, this.Position, target, targetOffset, length);
            this.Seek(length);
        }


        #region 特殊类型

        public IPAddress ReadIPAddress(int offset = 0, int length = 4)
        {
            return new IPAddress(this.ReadBytes(offset, length));
        }

        public IPEndPoint ReadIPEndPoint(int offset = 0, int length = 4)
        {
            return new IPEndPoint(this.ReadIPAddress(offset, length), this.ReadInt16());
        }


        #endregion

    }
}
